package com.cn.encryp;

import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

/**
 * @description:  AES对称加密算法
 * @Author 朱明川
 * @Date 2023/7/20 11:13
 * @Version 1.0
 */
public class AES {

    private static final String AES_ALGORITHM = "AES";
    // AES密钥
    private static final String AES_SECRET_KEY = "4128D9CDAC7E2F82951CBAF7FDFE675B";
    // AES加密模式为GCM，填充方式为NoPadding
// AES-GCM 是流加密（Stream cipher）算法，所以对应的填充模式为 NoPadding，即无需填充。
    private static final String AES_TRANSFORMATION = "AES/GCM/NoPadding";
    // 加密器
    private static Cipher encryptionCipher;
    // 解密器
    private static Cipher decryptionCipher;

    /**
     * 完成一些初始化工作
     */
    public static void init() throws Exception {
        // 将AES密钥转换为SecretKeySpec对象
        SecretKeySpec secretKeySpec = new SecretKeySpec(AES_SECRET_KEY.getBytes(), AES_ALGORITHM);
        // 使用指定的AES加密模式和填充方式获取对应的加密器并初始化
        encryptionCipher = Cipher.getInstance(AES_TRANSFORMATION);
        encryptionCipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
        // 使用指定的AES加密模式和填充方式获取对应的解密器并初始化
        decryptionCipher = Cipher.getInstance(AES_TRANSFORMATION);
        decryptionCipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new GCMParameterSpec(128, encryptionCipher.getIV()));
    }

    /**
     * 加密
     */
    public static String encrypt(String data) throws Exception {
        byte[] dataInBytes = data.getBytes();
        // 加密数据
        byte[] encryptedBytes = encryptionCipher.doFinal(dataInBytes);
        return Base64.getEncoder().encodeToString(encryptedBytes);
    }

    /**
     * 解密
     */
    public static String decrypt(String encryptedData) throws Exception {
        byte[] dataInBytes = Base64.getDecoder().decode(encryptedData);
        // 解密数据
        byte[] decryptedBytes = decryptionCipher.doFinal(dataInBytes);
        return new String(decryptedBytes, StandardCharsets.UTF_8);
    }

    public static void main(String[] args) throws Exception {
        String originalString = "Java学习 + 面试指南：javaguide.cn";
        init();
        String encryptedData = encrypt(originalString);
        String decryptedData = decrypt(encryptedData);
        System.out.println("Original String: " + originalString);
        System.out.println("AES Encrypted Data : " + encryptedData);
        System.out.println("AES Decrypted Data : " + decryptedData);
    }

}
